<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>训练SQL - Telchina.AI</title>
    <link href="./assets/index.css" rel="stylesheet">
    <script src="./js/tailwind.min.js"></script>
    <script src="./assets/auth.js"></script>
    <script src="./assets/api-client.js"></script>
    <link rel="icon" type="image/svg+xml" href="./vanna.svg" />
</head>
<body class="bg-gray-50 dark:bg-gray-900">
    <div class="min-h-screen flex flex-col pt-16">
        <!-- 顶部导航 -->
        <nav class="fixed top-0 left-0 right-0 z-50 bg-white dark:bg-gray-800 shadow-sm border-b border-gray-200 dark:border-gray-700">
            <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
                <div class="flex justify-between h-16">
                    <div class="flex items-center">
                        <img src="./telchina.svg" alt="Telchina.AI" class="h-8 w-8 mr-3">
                        <h1 class="text-xl font-semibold text-gray-900 dark:text-white">训练SQL管理</h1>
                    </div>
                    <div class="flex items-center space-x-4">
                        <a href="index.html" class="bg-green-600 hover:bg-green-700 text-white px-4 py-2 rounded-lg font-medium flex items-center">
                            <svg class="w-4 h-4 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                                <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6"></path>
                            </svg>
                            返回首页
                        </a>
                        <a href="chat.html" class="text-gray-600 hover:text-gray-900 dark:text-gray-300 dark:hover:text-white px-3 py-2 rounded-md text-sm font-medium">AI对话</a>
                        <a href="templates.html" class="text-gray-600 hover:text-gray-900 dark:text-gray-300 dark:hover:text-white px-3 py-2 rounded-md text-sm font-medium">SQL模板</a>
                        <button id="darkModeToggle" class="p-2 rounded-md text-gray-600 hover:text-gray-900 dark:text-gray-300 dark:hover:text-white">
                            <!-- 浅色模式图标 (全月) -->
                            <svg id="lightModeIcon" class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                                <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 3v1m0 16v1m9-9h-1M4 12H3m15.364 6.364l-.707-.707M6.343 6.343l-.707-.707m12.728 0l-.707.707M6.343 17.657l-.707.707M16 12a4 4 0 11-8 0 4 4 0 018 0z"></path>
                            </svg>
                            <!-- 暗黑模式图标 (半月) -->
                            <svg id="darkModeIcon" class="w-5 h-5 hidden" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                                <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M20.354 15.354A9 9 0 018.646 3.646 9.003 9.003 0 0012 21a9.003 9.003 0 008.354-5.646z"></path>
                            </svg>
                        </button>
                    </div>
                </div>
            </div>
        </nav>

        <!-- 主要内容区域 -->
        <div class="flex-1 p-6">
            <div class="max-w-7xl mx-auto">
                <!-- 页面标题和操作按钮 -->
                <div class="flex justify-between items-center mb-6">
                    <div>
                        <h2 class="text-2xl font-bold text-gray-900 dark:text-white">训练数据管理</h2>
                        <p class="text-gray-600 dark:text-gray-400 mt-1">管理AI模型的训练数据，包括问题、SQL语句、DDL和文档</p>
                    </div>
                    <div class="flex space-x-3">
                        <!-- 导出按钮 -->
                        <button id="exportBtn" class="bg-green-600 hover:bg-green-700 text-white font-medium py-2 px-4 rounded-lg flex items-center space-x-2">
                            <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                                <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 10v6m0 0l-3-3m3 3l3-3m2 8H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"></path>
                            </svg>
                            <span>导出数据</span>
                        </button>
                        <!-- 导入按钮 -->
                        <button id="importBtn" class="bg-purple-600 hover:bg-purple-700 text-white font-medium py-2 px-4 rounded-lg flex items-center space-x-2">
                            <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                                <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M7 16a4 4 0 01-.88-7.903A5 5 0 1115.9 6L16 6a5 5 0 011 9.9M9 19l3 3m0 0l3-3m-3 3V10"></path>
                            </svg>
                            <span>导入数据</span>
                        </button>
                        <!-- 原有的添加按钮 -->
                        <button id="addTrainingBtn" class="bg-blue-600 hover:bg-blue-700 text-white font-medium py-2 px-4 rounded-lg flex items-center space-x-2">
                            <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                                <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4v16m8-8H4"></path>
                            </svg>
                            <span>添加训练数据</span>
                        </button>
                    </div>
                </div>

                <!-- 训练数据表格 -->
                <div class="bg-white dark:bg-gray-800 shadow-sm rounded-lg border border-gray-200 dark:border-gray-700">
                    <div class="px-6 py-4 border-b border-gray-200 dark:border-gray-700">
                        <div class="flex justify-between items-center">
                            <h3 class="text-lg font-medium text-gray-900 dark:text-white">训练数据列表</h3>
                            <button id="refreshBtn" class="text-gray-600 hover:text-gray-900 dark:text-gray-400 dark:hover:text-white">
                                <svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                                    <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"></path>
                                </svg>
                            </button>
                        </div>
                    </div>
                    <div class="overflow-x-auto">
                        <table class="min-w-full divide-y divide-gray-200 dark:divide-gray-700 table-fixed">
                            <thead class="bg-gray-50 dark:bg-gray-800">
                                <tr>
                                    <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider w-20">ID</th>
                                    <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider w-1/4">问题</th>
                                    <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider w-20">类型</th>
                                    <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider w-1/3">内容</th>
                                    <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider w-20">操作</th>
                                </tr>
                            </thead>
                            <tbody id="trainingTableBody" class="bg-white dark:bg-gray-900 divide-y divide-gray-200 dark:divide-gray-700">
                                <!-- 数据将通过JavaScript动态加载 -->
                            </tbody>
                        </table>
                    </div>
                    <div id="loadingIndicator" class="text-center py-8">
                        <svg class="animate-spin w-8 h-8 mx-auto text-gray-400" fill="none" viewBox="0 0 24 24">
                            <circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
                            <path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
                        </svg>
                        <p class="text-gray-500 dark:text-gray-400 mt-2">加载中...</p>
                    </div>
                    <div id="emptyState" class="text-center py-12 hidden">
                        <svg class="w-16 h-16 mx-auto text-gray-300 dark:text-gray-600 mb-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                            <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"></path>
                        </svg>
                        <p class="text-gray-500 dark:text-gray-400 text-lg font-medium">暂无训练数据</p>
                        <p class="text-gray-400 dark:text-gray-500 text-sm mt-1">点击上方按钮添加第一条训练数据</p>
                    </div>
                </div>
            </div>
        </div>
    </div>

    <!-- 添加/编辑训练数据模态框 -->
    <div id="trainingModal" class="fixed inset-0 bg-gray-600 bg-opacity-50 hidden z-50">
        <div class="flex items-center justify-center min-h-screen p-4">
            <div class="bg-white dark:bg-gray-800 rounded-lg shadow-xl max-w-4xl w-full max-h-[90vh] overflow-y-auto">
                <div class="px-6 py-4 border-b border-gray-200 dark:border-gray-700">
                    <h3 id="modalTitle" class="text-lg font-medium text-gray-900 dark:text-white">添加训练数据</h3>
                </div>
                <form id="trainingForm" class="p-6 space-y-6">
                    <div>
                        <label for="questionInput" id="questionLabel" class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">问题 *</label>
                        <textarea id="questionInput" name="question" required 
                                class="w-full p-3 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent dark:bg-gray-700 dark:text-white" 
                                rows="3" placeholder="输入用户可能提出的问题..."></textarea>
                    </div>
                    <div>
                        <label for="typeSelect" class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">类型 *</label>
                        <select id="typeSelect" name="type" required 
                                class="w-full p-3 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent dark:bg-gray-700 dark:text-white">
                            <option value="">请选择类型</option>
                            <option value="sql">SQL语句</option>
                            <option value="ddl">DDL语句</option>
                            <option value="doc">文档说明</option>
                        </select>
                    </div>
                    <div>
                        <label for="contentInput" class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">内容 *</label>
                        <textarea id="contentInput" name="content" required 
                                class="w-full p-3 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent dark:bg-gray-700 dark:text-white font-mono" 
                                rows="8" placeholder="请输入相应的内容..."></textarea>
                    </div>
                    <div class="flex justify-end space-x-3 pt-4 border-t border-gray-200 dark:border-gray-700">
                        <button type="button" id="cancelBtn" class="px-4 py-2 text-gray-700 dark:text-gray-300 bg-gray-100 dark:bg-gray-700 hover:bg-gray-200 dark:hover:bg-gray-600 rounded-lg font-medium">
                            取消
                        </button>
                        <button type="submit" id="submitBtn" class="px-4 py-2 bg-blue-600 hover:bg-blue-700 text-white rounded-lg font-medium">
                            保存
                        </button>
                    </div>
                </form>
            </div>
        </div>
    </div>

    <!-- 确认删除模态框 -->
    <div id="deleteModal" class="fixed inset-0 bg-gray-600 bg-opacity-50 hidden z-50">
        <div class="flex items-center justify-center min-h-screen p-4">
            <div class="bg-white dark:bg-gray-800 rounded-lg shadow-xl max-w-md w-full">
                <div class="p-6">
                    <div class="flex items-center mb-4">
                        <svg class="w-6 h-6 text-red-600 mr-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                            <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4c-.77-.833-1.964-.833-2.732 0L4.082 16.5c-.77.833.192 2.5 1.732 2.5z"></path>
                        </svg>
                        <h3 class="text-lg font-medium text-gray-900 dark:text-white">确认删除</h3>
                    </div>
                    <p class="text-gray-600 dark:text-gray-400 mb-6">确定要删除这条训练数据吗？此操作无法撤销。</p>
                    <div class="flex justify-end space-x-3">
                        <button id="cancelDeleteBtn" class="px-4 py-2 text-gray-700 dark:text-gray-300 bg-gray-100 dark:bg-gray-700 hover:bg-gray-200 dark:hover:bg-gray-600 rounded-lg font-medium">
                            取消
                        </button>
                        <button id="confirmDeleteBtn" class="px-4 py-2 bg-red-600 hover:bg-red-700 text-white rounded-lg font-medium">
                            删除
                        </button>
                    </div>
                </div>
            </div>
        </div>
    </div>

    <!-- 导入数据模态框 -->
    <div id="importModal" class="fixed inset-0 bg-gray-600 bg-opacity-50 hidden z-50">
        <div class="flex items-center justify-center min-h-screen p-4">
            <div class="bg-white dark:bg-gray-800 rounded-lg shadow-xl max-w-2xl w-full">
                <div class="px-6 py-4 border-b border-gray-200 dark:border-gray-700">
                    <h3 class="text-lg font-medium text-gray-900 dark:text-white">导入训练数据</h3>
                </div>
                <div class="p-6">
                    <div class="mb-4">
                        <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">
                            选择JSON文件
                        </label>
                        <div class="mt-1 flex justify-center px-6 pt-5 pb-6 border-2 border-gray-300 border-dashed rounded-md hover:border-gray-400 dark:border-gray-600 dark:hover:border-gray-500">
                            <div class="space-y-1 text-center">
                                <svg class="mx-auto h-12 w-12 text-gray-400" stroke="currentColor" fill="none" viewBox="0 0 48 48">
                                    <path d="M28 8H12a4 4 0 00-4 4v20m32-12v8m0 0v8a4 4 0 01-4 4H12a4 4 0 01-4-4v-4m32-4l-3.172-3.172a4 4 0 00-5.656 0L28 28M8 32l9.172-9.172a4 4 0 015.656 0L28 28m0 0l4 4m4-24h8m-4-4v8m-12 4h.02" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
                                </svg>
                                <div class="flex text-sm text-gray-600 dark:text-gray-400">
                                    <label for="fileInput" class="relative cursor-pointer bg-white dark:bg-gray-800 rounded-md font-medium text-blue-600 hover:text-blue-500 focus-within:outline-none focus-within:ring-2 focus-within:ring-offset-2 focus-within:ring-blue-500">
                                        <span>选择文件</span>
                                        <input id="fileInput" name="file" type="file" accept=".json" class="sr-only">
                                    </label>
                                    <p class="pl-1">或拖拽到此处</p>
                                </div>
                                <p class="text-xs text-gray-500 dark:text-gray-400">仅支持JSON格式文件</p>
                            </div>
                        </div>
                    </div>
                    <div id="fileInfo" class="hidden mb-4 p-3 bg-blue-50 dark:bg-blue-900 rounded-lg">
                        <p class="text-sm text-blue-800 dark:text-blue-200">已选择文件: <span id="fileName"></span></p>
                        <p class="text-sm text-blue-600 dark:text-blue-300">文件大小: <span id="fileSize"></span></p>
                    </div>
                    <div id="importPreview" class="hidden mb-4">
                        <h4 class="text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">数据预览:</h4>
                        <div class="bg-gray-50 dark:bg-gray-700 rounded-lg p-3 max-h-40 overflow-y-auto">
                            <pre id="previewContent" class="text-xs text-gray-600 dark:text-gray-300"></pre>
                        </div>
                    </div>
                </div>
                <div class="px-6 py-4 border-t border-gray-200 dark:border-gray-700 flex justify-end space-x-3">
                    <button id="cancelImportBtn" class="px-4 py-2 text-gray-700 dark:text-gray-300 bg-gray-100 dark:bg-gray-700 hover:bg-gray-200 dark:hover:bg-gray-600 rounded-lg font-medium">
                        取消
                    </button>
                    <button id="confirmImportBtn" class="px-4 py-2 bg-purple-600 hover:bg-purple-700 text-white rounded-lg font-medium" disabled>
                        导入数据
                    </button>
                </div>
            </div>
        </div>
    </div>

    <script>
        class TrainingManager {
            constructor() {
                this.trainingData = [];
                this.currentDeleteId = null;
                this.currentEditId = null;
                this.isEditMode = false;
                this.initializeElements();
                this.bindEvents();
                this.loadTrainingData();
                this.initializeDarkMode();
            }

            initializeElements() {
                this.trainingTableBody = document.getElementById('trainingTableBody');
                this.loadingIndicator = document.getElementById('loadingIndicator');
                this.emptyState = document.getElementById('emptyState');
                this.addTrainingBtn = document.getElementById('addTrainingBtn');
                this.refreshBtn = document.getElementById('refreshBtn');
                this.trainingModal = document.getElementById('trainingModal');
                this.trainingForm = document.getElementById('trainingForm');
                this.modalTitle = document.getElementById('modalTitle');
                this.cancelBtn = document.getElementById('cancelBtn');
                this.submitBtn = document.getElementById('submitBtn');
                this.deleteModal = document.getElementById('deleteModal');
                this.cancelDeleteBtn = document.getElementById('cancelDeleteBtn');
                this.confirmDeleteBtn = document.getElementById('confirmDeleteBtn');
                this.darkModeToggle = document.getElementById('darkModeToggle');
                this.exportBtn = document.getElementById('exportBtn');
                this.importBtn = document.getElementById('importBtn');
                this.importModal = document.getElementById('importModal');
                this.fileInput = document.getElementById('fileInput');
                this.fileInfo = document.getElementById('fileInfo');
                this.fileName = document.getElementById('fileName');
                this.fileSize = document.getElementById('fileSize');
                this.importPreview = document.getElementById('importPreview');
                this.previewContent = document.getElementById('previewContent');
                this.cancelImportBtn = document.getElementById('cancelImportBtn');
                this.confirmImportBtn = document.getElementById('confirmImportBtn');
            }

            bindEvents() {
                this.addTrainingBtn.addEventListener('click', () => this.showAddModal());
                this.refreshBtn.addEventListener('click', () => this.loadTrainingData());
                this.cancelBtn.addEventListener('click', () => this.hideModal());
                this.trainingForm.addEventListener('submit', (e) => this.handleSubmit(e));
                this.cancelDeleteBtn.addEventListener('click', () => this.hideDeleteModal());
                this.confirmDeleteBtn.addEventListener('click', () => this.confirmDelete());
                this.darkModeToggle.addEventListener('click', () => this.toggleDarkMode());
                this.exportBtn.addEventListener('click', () => this.exportData());
                this.importBtn.addEventListener('click', () => this.showImportModal());
                this.fileInput.addEventListener('change', (e) => this.handleFileSelect(e));
                this.cancelImportBtn.addEventListener('click', () => this.hideImportModal());
                this.confirmImportBtn.addEventListener('click', () => this.importData());
                
                // 类型选择变化事件
                document.getElementById('typeSelect').addEventListener('change', (e) => {
                    const contentInput = document.getElementById('contentInput');
                    const questionInput = document.getElementById('questionInput');
                    const questionLabel = document.getElementById('questionLabel');
                    const selectedType = e.target.value;
                    
                    switch(selectedType) {
                        case 'sql':
                            contentInput.placeholder = 'SELECT * FROM table_name WHERE...';
                            questionInput.required = true;
                            questionLabel.textContent = '问题 *';
                            break;
                        case 'ddl':
                            contentInput.placeholder = 'CREATE TABLE table_name (...)';
                            questionInput.required = false;
                            questionLabel.textContent = '问题';
                            break;
                        case 'doc':
                            contentInput.placeholder = '相关的文档说明或注释...';
                            questionInput.required = false;
                            questionLabel.textContent = '问题';
                            break;
                        default:
                            contentInput.placeholder = '请输入相应的内容...';
                            questionInput.required = true;
                            questionLabel.textContent = '问题 *';
                    }
                });
                
                // 点击模态框外部关闭
                this.trainingModal.addEventListener('click', (e) => {
                    if (e.target === this.trainingModal) this.hideModal();
                });
                this.deleteModal.addEventListener('click', (e) => {
                    if (e.target === this.deleteModal) this.hideDeleteModal();
                });
                this.importModal.addEventListener('click', (e) => {
                    if (e.target === this.importModal) this.hideImportModal();
                });
            }

            updateThemeIcon(isDark) {
                const lightIcon = document.getElementById('lightModeIcon');
                const darkIcon = document.getElementById('darkModeIcon');
                
                if (isDark) {
                    // 暗黑模式：显示半月图标
                    lightIcon.classList.add('hidden');
                    darkIcon.classList.remove('hidden');
                } else {
                    // 浅色模式：显示全月图标
                    lightIcon.classList.remove('hidden');
                    darkIcon.classList.add('hidden');
                }
            }

            initializeDarkMode() {
                const isDark = localStorage.getItem('darkMode') === 'true';
                if (isDark) {
                    document.documentElement.classList.add('dark');
                }
                this.updateThemeIcon(isDark);
            }

            toggleDarkMode() {
                const isDark = document.documentElement.classList.toggle('dark');
                localStorage.setItem('darkMode', isDark.toString());
                this.updateThemeIcon(isDark);
            }

            async loadTrainingData() {
                try {
                    this.showLoading();
                    const response = await apiClient.get('/api/v0/get_training_data');
                    const data = await response.json();
                    console.log('获取的训练数据:', data);
                    if (data.type === 'df') {
                        this.trainingData = JSON.parse(data.df);
                        console.log('加载的训练数据:', this.trainingData);
                        this.renderTrainingData();
                    } else {
                        throw new Error(data.error || '加载失败');
                    }
                } catch (error) {
                    console.error('加载训练数据失败:', error);
                    this.showError('加载训练数据失败');
                } finally {
                    this.hideLoading();
                }
            }

            renderTrainingData() {
                if (this.trainingData.length === 0) {
                    this.showEmptyState();
                    return;
                }

                this.trainingTableBody.innerHTML = '';
                this.trainingData.forEach(item => {
                    const row = this.createTableRow(item);
                    this.trainingTableBody.appendChild(row);
                });
                this.hideEmptyState();
            }

            createTableRow(item) {
                const row = document.createElement('tr');
                row.className = 'hover:bg-gray-50 dark:hover:bg-gray-800';
                
                const truncateText = (text, maxLength = 100) => {
                    if (!text) return '';
                    return text.length > maxLength ? text.substring(0, maxLength) + '...' : text;
                };

                const createExpandableCell = (content, isCode = false) => {
                    const fullContent = this.escapeHtml(content || '');
                    const truncatedContent = this.escapeHtml(truncateText(content, 100));
                    const needsExpansion = (content || '').length > 100;
                    
                    if (!needsExpansion) {
                        return isCode ? 
                            `<code class="text-xs bg-gray-100 dark:bg-gray-700 px-2 py-1 rounded block whitespace-pre-wrap">${fullContent}</code>` :
                            `<p class="whitespace-pre-wrap">${fullContent}</p>`;
                    }
                    
                    const uniqueId = 'content_' + Math.random().toString(36).substr(2, 9);
                    return `
                        <div>
                            <div id="${uniqueId}_short" class="${isCode ? 'text-xs bg-gray-100 dark:bg-gray-700 px-2 py-1 rounded' : ''}">
                                ${isCode ? `<code class="whitespace-pre-wrap">${truncatedContent}</code>` : `<p class="whitespace-pre-wrap">${truncatedContent}</p>`}
                            </div>
                            <div id="${uniqueId}_full" class="hidden ${isCode ? 'text-xs bg-gray-100 dark:bg-gray-700 px-2 py-1 rounded' : ''}">
                                ${isCode ? `<code class="whitespace-pre-wrap">${fullContent}</code>` : `<p class="whitespace-pre-wrap">${fullContent}</p>`}
                            </div>
                            <button onclick="trainingManager.toggleContent('${uniqueId}')" class="text-blue-600 hover:text-blue-800 dark:text-blue-400 text-xs mt-1">
                                <span id="${uniqueId}_btn">展开</span>
                            </button>
                        </div>
                    `;
                };

                // 根据ID判断数据类型
                const getDataType = (id) => {
                    if (id.includes('sql')) return 'SQL';
                    if (id.includes('ddl')) return 'DDL';
                    if (id.includes('doc')) return '文档';
                    return '未知';
                };

                // 判断是否为代码类型
                const isCodeType = (id) => {
                    return id.includes('sql') || id.includes('ddl');
                };

                const dataType = getDataType(item.id || '');
                const isCode = isCodeType(item.id || '');

                row.innerHTML = `
                    <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900 dark:text-gray-100 w-20">${this.escapeHtml(item.id || '')}</td>
                    <td class="px-6 py-4 text-sm text-gray-900 dark:text-gray-100 w-1/4">
                        <div class="max-w-sm">
                            ${createExpandableCell(item.question)}
                        </div>
                    </td>
                    <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900 dark:text-gray-100 w-20">
                        <span class="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium ${
                            dataType === 'SQL' ? 'bg-blue-100 text-blue-800 dark:bg-blue-900 dark:text-blue-200' :
                            dataType === 'DDL' ? 'bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-200' :
                            dataType === '文档' ? 'bg-yellow-100 text-yellow-800 dark:bg-yellow-900 dark:text-yellow-200' :
                            'bg-gray-100 text-gray-800 dark:bg-gray-900 dark:text-gray-200'
                        }">
                            ${dataType}
                        </span>
                    </td>
                    <td class="px-6 py-4 text-sm text-gray-900 dark:text-gray-100 w-1/3">
                        <div class="max-w-md">
                            ${createExpandableCell(item.content, isCode)}
                        </div>
                    </td>
                    <td class="px-6 py-4 whitespace-nowrap text-sm font-medium w-20">
                        <div class="flex space-x-2">
                            <button class="text-blue-600 hover:text-blue-900 dark:text-blue-400 dark:hover:text-blue-300" onclick="trainingManager.showEditModal('${item.id}')" title="编辑">
                                <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                                    <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z"></path>
                                </svg>
                            </button>
                            <button class="text-red-600 hover:text-red-900 dark:text-red-400 dark:hover:text-red-300" onclick="trainingManager.showDeleteModal('${item.id}')" title="删除">
                                <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                                    <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"></path>
                                </svg>
                            </button>
                        </div>
                    </td>
                `;
                
                return row;
            }

            toggleContent(uniqueId) {
                const shortDiv = document.getElementById(uniqueId + '_short');
                const fullDiv = document.getElementById(uniqueId + '_full');
                const btn = document.getElementById(uniqueId + '_btn');
                
                if (shortDiv.classList.contains('hidden')) {
                    // 当前显示完整内容，切换到简短内容
                    shortDiv.classList.remove('hidden');
                    fullDiv.classList.add('hidden');
                    btn.textContent = '展开';
                } else {
                    // 当前显示简短内容，切换到完整内容
                    shortDiv.classList.add('hidden');
                    fullDiv.classList.remove('hidden');
                    btn.textContent = '收起';
                }
            }

            showAddModal() {
                this.isEditMode = false;
                this.currentEditId = null;
                this.modalTitle.textContent = '添加训练数据';
                this.submitBtn.textContent = '保存';
                this.trainingForm.reset();
                
                // 重置问题字段为必填状态
                const questionInput = document.getElementById('questionInput');
                const questionLabel = document.getElementById('questionLabel');
                questionInput.required = true;
                questionLabel.textContent = '问题 *';
                
                this.trainingModal.classList.remove('hidden');
                document.getElementById('questionInput').focus();
            }

            showEditModal(id) {
                this.isEditMode = true;
                this.currentEditId = id;
                this.modalTitle.textContent = '编辑训练数据';
                this.submitBtn.textContent = '更新';
                
                // 查找要编辑的数据
                const itemToEdit = this.trainingData.find(item => item.id === id);
                if (itemToEdit) {
                    // 填充表单数据
                    document.getElementById('questionInput').value = itemToEdit.question || '';
                    document.getElementById('contentInput').value = itemToEdit.content || '';
                    
                    // 根据ID判断类型并设置选择框
                    const typeSelect = document.getElementById('typeSelect');
                    const questionInput = document.getElementById('questionInput');
                    const questionLabel = document.getElementById('questionLabel');
                    
                    if (itemToEdit.id.includes('sql')) {
                        typeSelect.value = 'sql';
                        questionInput.required = true;
                        questionLabel.textContent = '问题 *';
                    } else if (itemToEdit.id.includes('ddl')) {
                        typeSelect.value = 'ddl';
                        questionInput.required = false;
                        questionLabel.textContent = '问题';
                    } else if (itemToEdit.id.includes('doc')) {
                        typeSelect.value = 'doc';
                        questionInput.required = false;
                        questionLabel.textContent = '问题';
                    }
                    
                    // 触发类型选择变化事件以更新占位符
                    typeSelect.dispatchEvent(new Event('change'));
                }
                
                this.trainingModal.classList.remove('hidden');
                document.getElementById('questionInput').focus();
            }

            hideModal() {
                this.trainingModal.classList.add('hidden');
                this.isEditMode = false;
                this.currentEditId = null;
            }

            showDeleteModal(id) {
                this.currentDeleteId = id;
                this.deleteModal.classList.remove('hidden');
            }

            hideDeleteModal() {
                this.deleteModal.classList.add('hidden');
                this.currentDeleteId = null;
            }

            async handleSubmit(e) {
                e.preventDefault();
                
                const formData = new FormData(this.trainingForm);
                const question = formData.get('question');
                const content = formData.get('content');
                const type = formData.get('type');
                
                // 根据类型构建API期望的数据格式
                const data = {
                    question: question || null,
                    sql: null,
                    ddl: null,
                    documentation: null
                };
                
                // 根据类型设置对应字段
                switch(type) {
                    case 'sql':
                        data.sql = content;
                        break;
                    case 'ddl':
                        data.ddl = content;
                        break;
                    case 'doc':
                        data.documentation = content;
                        break;
                    default:
                        throw new Error('请选择有效的数据类型');
                }

                try {
                    this.submitBtn.disabled = true;
                    
                    if (this.isEditMode && this.currentEditId) {
                        // 编辑模式：先删除后添加
                        this.submitBtn.textContent = '更新中...';
                        
                        // 先删除原数据
                        const deleteResponse = await apiClient.post('/api/v0/remove_training_data', { id: this.currentEditId });
                        const deleteResult = await deleteResponse.json();
                        if (!deleteResult.success) {
                            throw new Error(deleteResult.error || '删除原数据失败');
                        }
                        
                        // 再添加新数据
                        const addResponse = await apiClient.post('/api/v0/train', data);
                        const addResult = await addResponse.json();
                        if (addResult.id) {
                            this.showSuccess('训练数据更新成功');
                            this.hideModal();
                            this.loadTrainingData();
                        } else {
                            throw new Error(addResult.error || '添加新数据失败');
                        }
                    } else {
                        // 添加模式
                        this.submitBtn.textContent = '保存中...';
                        
                        const response = await apiClient.post('/api/v0/train', data);
                        const result = await response.json();
                        
                        if (result.id) {
                            this.showSuccess('训练数据添加成功');
                            this.hideModal();
                            this.loadTrainingData();
                        } else {
                            throw new Error(result.error || '添加失败');
                        }
                    }
                } catch (error) {
                    console.error(this.isEditMode ? '更新训练数据失败:' : '添加训练数据失败:', error);
                    this.showError((this.isEditMode ? '更新训练数据失败: ' : '添加训练数据失败: ') + error.message);
                } finally {
                    this.submitBtn.disabled = false;
                    this.submitBtn.textContent = this.isEditMode ? '更新' : '保存';
                }
            }

            async confirmDelete() {
                if (!this.currentDeleteId) return;

                try {
                    this.confirmDeleteBtn.disabled = true;
                    this.confirmDeleteBtn.textContent = '删除中...';
                    
                    const response = await apiClient.post('/api/v0/remove_training_data', { id: this.currentDeleteId });
                    const result = await response.json();
                    
                    if (result.success) {
                        this.showSuccess('训练数据删除成功');
                        this.hideDeleteModal();
                        this.loadTrainingData();
                    } else {
                        throw new Error(result.error || '删除失败');
                    }
                } catch (error) {
                    console.error('删除训练数据失败:', error);
                    this.showError('删除训练数据失败: ' + error.message);
                } finally {
                    this.confirmDeleteBtn.disabled = false;
                    this.confirmDeleteBtn.textContent = '删除';
                }
            }

            showLoading() {
                this.loadingIndicator.classList.remove('hidden');
                this.emptyState.classList.add('hidden');
            }

            hideLoading() {
                this.loadingIndicator.classList.add('hidden');
            }

            showEmptyState() {
                this.emptyState.classList.remove('hidden');
                this.trainingTableBody.innerHTML = '';
            }

            hideEmptyState() {
                this.emptyState.classList.add('hidden');
            }

            showSuccess(message) {
                this.showNotification(message, 'success');
            }

            showError(message) {
                this.showNotification(message, 'error');
            }

            showNotification(message, type) {
                const notification = document.createElement('div');
                notification.className = `fixed top-4 right-4 z-50 p-4 rounded-lg shadow-lg ${
                    type === 'success' 
                        ? 'bg-green-100 text-green-800 border border-green-200' 
                        : 'bg-red-100 text-red-800 border border-red-200'
                }`;
                notification.textContent = message;
                
                document.body.appendChild(notification);
                
                setTimeout(() => {
                    notification.remove();
                }, 3000);
            }

            escapeHtml(text) {
                const div = document.createElement('div');
                div.textContent = text;
                return div.innerHTML;
            }

            // 导出数据功能
            exportData() {
                try {
                    if (this.trainingData.length === 0) {
                        this.showError('没有可导出的训练数据');
                        return;
                    }
                    
                    const dataToExport = {
                        exportTime: new Date().toISOString(),
                        version: '1.0',
                        count: this.trainingData.length,
                        data: this.trainingData
                    };
                    
                    const jsonString = JSON.stringify(dataToExport, null, 2);
                    const blob = new Blob([jsonString], { type: 'application/json' });
                    const url = URL.createObjectURL(blob);
                    
                    const a = document.createElement('a');
                    a.href = url;
                    a.download = `training_data_${new Date().toISOString().split('T')[0]}.json`;
                    document.body.appendChild(a);
                    a.click();
                    document.body.removeChild(a);
                    URL.revokeObjectURL(url);
                    
                    this.showSuccess(`成功导出 ${this.trainingData.length} 条训练数据`);
                } catch (error) {
                    console.error('导出数据失败:', error);
                    this.showError('导出数据失败: ' + error.message);
                }
            }

            // 显示导入模态框
            showImportModal() {
                this.importModal.classList.remove('hidden');
                this.resetImportForm();
            }

            // 隐藏导入模态框
            hideImportModal() {
                this.importModal.classList.add('hidden');
                this.resetImportForm();
            }

            // 重置导入表单
            resetImportForm() {
                this.fileInput.value = '';
                this.fileInfo.classList.add('hidden');
                this.importPreview.classList.add('hidden');
                this.confirmImportBtn.disabled = true;
                this.selectedFileData = null;
            }

            // 处理文件选择
            handleFileSelect(event) {
                const file = event.target.files[0];
                if (!file) {
                    this.resetImportForm();
                    return;
                }
                
                if (file.type !== 'application/json' && !file.name.endsWith('.json')) {
                    this.showError('请选择JSON格式的文件');
                    this.resetImportForm();
                    return;
                }
                
                // 显示文件信息
                this.fileName.textContent = file.name;
                this.fileSize.textContent = this.formatFileSize(file.size);
                this.fileInfo.classList.remove('hidden');
                
                // 读取文件内容
                const reader = new FileReader();
                reader.onload = (e) => {
                    try {
                        const jsonData = JSON.parse(e.target.result);
                        this.validateImportData(jsonData);
                        this.selectedFileData = jsonData;
                        this.showPreview(jsonData);
                        this.confirmImportBtn.disabled = false;
                    } catch (error) {
                        this.showError('文件格式错误: ' + error.message);
                        this.resetImportForm();
                    }
                };
                reader.readAsText(file);
            }

            // 验证导入数据格式
            validateImportData(data) {
                if (!data || typeof data !== 'object') {
                    throw new Error('文件内容不是有效的JSON对象');
                }
                
                // 检查是否有data字段或直接是数组
                const trainingData = data.data || data;
                if (!Array.isArray(trainingData)) {
                    throw new Error('训练数据必须是数组格式');
                }
                
                if (trainingData.length === 0) {
                    throw new Error('文件中没有训练数据');
                }
                
                // 验证每条数据的格式
                trainingData.forEach((item, index) => {
                    if (!item.id) {
                        throw new Error(`第 ${index + 1} 条数据缺少ID字段`);
                    }
                    if (!item.content && !item.question) {
                        throw new Error(`第 ${index + 1} 条数据缺少内容或问题字段`);
                    }
                });
            }

            // 显示数据预览
            showPreview(data) {
                const trainingData = data.data || data;
                const preview = {
                    总数据量: trainingData.length,
                    数据类型统计: this.getDataTypeStats(trainingData),
                    前3条数据: trainingData.slice(0, 3).map(item => ({
                        id: item.id,
                        question: item.question ? item.question.substring(0, 50) + '...' : '',
                        content: item.content ? item.content.substring(0, 50) + '...' : ''
                    }))
                };
                
                this.previewContent.textContent = JSON.stringify(preview, null, 2);
                this.importPreview.classList.remove('hidden');
            }

            // 获取数据类型统计
            getDataTypeStats(data) {
                const stats = { SQL: 0, DDL: 0, 文档: 0, 其他: 0 };
                data.forEach(item => {
                    if (item.id.includes('sql')) stats.SQL++;
                    else if (item.id.includes('ddl')) stats.DDL++;
                    else if (item.id.includes('doc')) stats.文档++;
                    else stats.其他++;
                });
                return stats;
            }

            // 格式化文件大小
            formatFileSize(bytes) {
                if (bytes === 0) return '0 Bytes';
                const k = 1024;
                const sizes = ['Bytes', 'KB', 'MB', 'GB'];
                const i = Math.floor(Math.log(bytes) / Math.log(k));
                return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
            }

            // 导入数据
            async importData() {
                if (!this.selectedFileData) {
                    this.showError('请先选择要导入的文件');
                    return;
                }
                
                try {
                    this.confirmImportBtn.disabled = true;
                    this.confirmImportBtn.textContent = '导入中...';
                    
                    const trainingData = this.selectedFileData.data || this.selectedFileData;
                    let successCount = 0;
                    let errorCount = 0;
                    const errors = [];
                    
                    // 批量导入数据
                    for (let i = 0; i < trainingData.length; i++) {
                        const item = trainingData[i];
                        try {
                            // 构建API期望的数据格式
                            const data = {
                                question: item.question || null,
                                sql: null,
                                ddl: null,
                                documentation: null
                            };
                            
                            // 根据ID判断类型并设置对应字段
                            if (item.id.includes('sql')) {
                                data.sql = item.content;
                            } else if (item.id.includes('ddl')) {
                                data.ddl = item.content;
                            } else if (item.id.includes('doc')) {
                                data.documentation = item.content;
                            } else {
                                // 默认作为SQL处理
                                data.sql = item.content;
                            }
                            
                            const response = await apiClient.post('/api/v0/train', data);
                            const result = await response.json();
                            if (result.id) {
                                successCount++;
                            } else {
                                errorCount++;
                                errors.push(`第 ${i + 1} 条: ${result.error || '导入失败'}`);
                            }
                        } catch (error) {
                            errorCount++;
                            errors.push(`第 ${i + 1} 条: ${error.message}`);
                        }
                    }
                    
                    // 显示导入结果
                    if (successCount > 0) {
                        this.showSuccess(`成功导入 ${successCount} 条数据${errorCount > 0 ? `，失败 ${errorCount} 条` : ''}`);
                        this.hideImportModal();
                        this.loadTrainingData();
                    }
                    
                    if (errorCount > 0 && errors.length > 0) {
                        console.error('导入错误详情:', errors);
                        this.showError(`导入完成，但有 ${errorCount} 条数据失败`);
                    }
                    
                } catch (error) {
                    console.error('导入数据失败:', error);
                    this.showError('导入数据失败: ' + error.message);
                } finally {
                    this.confirmImportBtn.disabled = false;
                    this.confirmImportBtn.textContent = '导入数据';
                }
            }
        }

        // 初始化应用
        let trainingManager;
        document.addEventListener('DOMContentLoaded', () => {
            trainingManager = new TrainingManager();
        });
    </script>
</body>
</html>